package com.lx.iccp.activity.app.exceptionhandle;

import com.lx.iccp.support.common.config.I18NConfig;
import com.lx.iccp.support.common.enums.CodeEnum;
import com.lx.iccp.support.common.exception.EdiException;
import com.lx.iccp.support.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
@Slf4j
class GlobalDefaultExceptionHandler {
    private static final String CONTENT_TYPE = "Content-Type";
    private static final String APPLICATION_JSON = "application/json; charset=UTF-8";

    public static StringBuilder showParams(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>(16);
        Enumeration<?> paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement();

            String[] paramValues = request.getParameterValues(paramName);
            if (paramValues.length > 0) {
                String paramValue = paramValues[0];
                if (paramValue.length() != 0) {
                    map.put(paramName, paramValue);
                }
            }

        }
        Set<Map.Entry<String, Object>> set = map.entrySet();
        StringBuilder str = new StringBuilder();
        for (Map.Entry<String, Object> entry : set) {
            str.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        return str;
    }

    @ExceptionHandler(value = IllegalArgumentException.class)
    public ResponseEntity<Result<Object>> illegalArgumentErrorHandler(IllegalArgumentException e) {
        log.error("GlobalDefaultExceptionHandler illegalArgumentErrorHandler error={};{}", e.getMessage(), e);
        HttpHeaders headers = new HttpHeaders();
        headers.add(CONTENT_TYPE, APPLICATION_JSON);

        return new ResponseEntity<>(
                Result.errorResponse(CodeEnum.INVALIDINPUTDATA, e.getMessage()),
                headers,
                HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = IllegalStateException.class)
    public ResponseEntity<Result<Object>> illegalStateErrorHandler(IllegalStateException e) {

        HttpHeaders headers = new HttpHeaders();
        headers.add(CONTENT_TYPE, APPLICATION_JSON);

        return new ResponseEntity<>(
                Result.errorResponse(CodeEnum.INVALIDSTATE, e.getMessage()),
                headers,
                HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = DataAccessException.class)
    public ResponseEntity<Result<Object>> dataAccessErrorHandler(HttpServletRequest req, HttpServletResponse response,
                                                                 Exception e) {
        log.error("DB ERRO:" + req.getServletPath() + "?" + showParams(req).toString(), e);

        HttpHeaders headers = new HttpHeaders();
        headers.add(CONTENT_TYPE, APPLICATION_JSON);

        return new ResponseEntity<>(
                Result.errorResponse(CodeEnum.INTERNALSERVERERROR, I18NConfig.instance().getLocaleMessage("30018")),
                headers,
                HttpStatus.INTERNAL_SERVER_ERROR);
    }


    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Result<Object>> defaultErrorHandler(HttpServletRequest req, HttpServletResponse response,
                                                              Exception e) throws Exception {
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
            throw e;
        }

        HttpHeaders headers = new HttpHeaders();
        headers.add(CONTENT_TYPE, APPLICATION_JSON);

        if (e instanceof EdiException) {
            EdiException ee = (EdiException) e;
            if(CodeEnum.UNAUTHENTICATED.getCode().equals(ee.getCode())){
                return new ResponseEntity<>(
                        Result.errorResponse(ee.getCode(), ee.getTitle(), ee.getMsg(), ee.getMessage(), ee.getDetailInfo()),
                        headers,
                        HttpStatus.UNAUTHORIZED);
            }
            return new ResponseEntity<>(
                    Result.errorResponse(ee.getCode(), ee.getTitle(), ee.getMsg(), ee.getMessage(), ee.getDetailInfo()),
                    headers,
                    HttpStatus.BAD_REQUEST);
        } else {
            log.error("inside error ===============================e={}", e);
            return new ResponseEntity<>(
                    Result.errorResponse(CodeEnum.INTERNALSERVERERROR, e.getMessage()),
                    headers,
                    HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public  ResponseEntity<Result<Object>>  handleSizeLimitExceededException(MaxUploadSizeExceededException s){
        HttpHeaders headers = new HttpHeaders();
        headers.add(CONTENT_TYPE, APPLICATION_JSON);

        return new ResponseEntity<>(
                Result.errorResponse(CodeEnum.INTERNALSERVERERROR, "文件过大"),
                headers,
                HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

